// Copyright (c) Lawrence Livermore National Security, LLC and other VisIt
// Project developers.  See the top-level LICENSE file for dates and other
// details.  No copyright assignment is required to contribute to VisIt.

// ************************************************************************* //
//                        avtStreamGhostTestFileFormat.C                     //
// ************************************************************************* //

#include <avtStreamGhostTestFileFormat.h>

#include <string>

#include <vtkFloatArray.h>
#include <vtkRectilinearGrid.h>
#include <vtkUnstructuredGrid.h>

#include <avtDatabase.h>
#include <avtDatabaseMetaData.h>
#include <avtIsenburgSGG.h>
#include <avtVariableCache.h>

#include <Expression.h>

#include <InvalidVariableException.h>


using     std::string;


// ****************************************************************************
//  Method: avtStreamGhostTestFileFormat constructor
//
//  Programmer: childs -- generated by xml2avt
//  Creation:   Sun Feb 10 08:39:02 PDT 2008
//
// ****************************************************************************

avtStreamGhostTestFileFormat::avtStreamGhostTestFileFormat(const char *filename)
    : avtSTMDFileFormat(&filename, 1)
{
    // INITIALIZE DATA MEMBERS
}


// ****************************************************************************
//  Method: avtStreamGhostTestFileFormat::FreeUpResources
//
//  Purpose:
//      When VisIt is done focusing on a particular timestep, it asks that
//      timestep to free up any resources (memory, file descriptors) that
//      it has associated with it.  This method is the mechanism for doing
//      that.
//
//  Programmer: childs -- generated by xml2avt
//  Creation:   Sun Feb 10 08:39:02 PDT 2008
//
// ****************************************************************************

void
avtStreamGhostTestFileFormat::FreeUpResources(void)
{
}


// ****************************************************************************
//  Method: avtStreamGhostTestFileFormat::PopulateDatabaseMetaData
//
//  Purpose:
//      This database meta-data object is like a table of contents for the
//      file.  By populating it, you are telling the rest of VisIt what
//      information it can request from you.
//
//  Programmer: childs -- generated by xml2avt
//  Creation:   Sun Feb 10 08:39:02 PDT 2008
//
// ****************************************************************************

void
avtStreamGhostTestFileFormat::PopulateDatabaseMetaData(avtDatabaseMetaData *md)
{
    string meshname = "mesh";
    avtMeshType mt = AVT_RECTILINEAR_MESH;
    int nblocks = 8;
    int block_origin = 0;
    int spatial_dimension = 3;
    int topological_dimension = 3;
    double *extents = NULL;
    AddMeshToMetaData(md, meshname, mt, extents, nblocks, block_origin,
                      spatial_dimension, topological_dimension);

    string mesh_for_this_var = meshname; // ??? -- could be multiple meshes
    string varname = "var";
    avtCentering cent = AVT_NODECENT;
    AddScalarVarToMetaData(md, varname, mesh_for_this_var, cent);

    if (!avtDatabase::OnlyServeUpMetaData())
    {
        avtIsenburgSGG *db = new avtIsenburgSGG;
        db->SetNumberOfDomains(8);
        int sz[3] = { 5, 5, 5 };
        int ori[3];
        int nei[6];
        for (int i = 0 ; i < 8 ; i++)
        {
            bool loI = (i%2) == 0;
            bool loJ = ((i/2)%2) == 0;
            bool loK = ((i/4)%2) == 0;
            ori[0] = (loI ? 0 : 5);
            ori[1] = (loJ ? 0 : 5);
            ori[2] = (loK ? 0 : 5);
            nei[0] = (loI ? -1 : i-1);
            nei[1] = (loI ? i+1 : -1);
            nei[2] = (loJ ? -1 : i-2);
            nei[3] = (loJ ? i+2 : -1);
            nei[4] = (loK ? -1 : i-4);
            nei[5] = (loK ? i+4 : -1);
            db->SetInfoForDomain(i, ori, sz, nei);
        }
        db->FinalizeDomainInformation();
        void_ref_ptr vr = void_ref_ptr(db, avtStreamingGhostGenerator::Destruct);
        cache->CacheVoidRef("any_mesh",
                       AUXILIARY_DATA_STREAMING_GHOST_GENERATION, -1, -1, vr);
    }
}


// ****************************************************************************
//  Method: avtStreamGhostTestFileFormat::GetMesh
//
//  Purpose:
//      Gets the mesh associated with this file.  The mesh is returned as a
//      derived type of vtkDataSet (ie vtkRectilinearGrid, vtkStructuredGrid,
//      vtkUnstructuredGrid, etc).
//
//  Arguments:
//      domain      The index of the domain.  If there are NDomains, this
//                  value is guaranteed to be between 0 and NDomains-1,
//                  regardless of block origin.
//      meshname    The name of the mesh of interest.  This can be ignored if
//                  there is only one mesh.
//
//  Programmer: childs -- generated by xml2avt
//  Creation:   Sun Feb 10 08:39:02 PDT 2008
//
// ****************************************************************************

vtkDataSet *
avtStreamGhostTestFileFormat::GetMesh(int domain, const char *meshname)
{
    int  i;

    vtkFloatArray *X = vtkFloatArray::New();
    X->SetNumberOfTuples(5);
    double Xstart = ( ((domain % 2) == 1) ? 5. : 0. );
    vtkFloatArray *Y = vtkFloatArray::New();
    Y->SetNumberOfTuples(5);
    double Ystart = ( (((domain/2) % 2) == 1) ? 5. : 0. );
    vtkFloatArray *Z = vtkFloatArray::New();
    Z->SetNumberOfTuples(5);
    double Zstart = ( (((domain/4) % 2) == 1) ? 5. : 0. );
    for (i = 0 ; i < 5 ; i++)
    {
        X->SetTuple1(i, Xstart+i);
        Y->SetTuple1(i, Ystart+i);
        Z->SetTuple1(i, Zstart+i);
    }

    vtkRectilinearGrid *grid = vtkRectilinearGrid::New();
    grid->SetDimensions(5,5,5);
    grid->SetXCoordinates(X);
    X->Delete();
    grid->SetYCoordinates(Y);
    Y->Delete();
    grid->SetZCoordinates(Z);
    Z->Delete();

    return grid;
}


// ****************************************************************************
//  Method: avtStreamGhostTestFileFormat::GetVar
//
//  Purpose:
//      Gets a scalar variable associated with this file.  Although VTK has
//      support for many different types, the best bet is vtkFloatArray, since
//      that is supported everywhere through VisIt.
//
//  Arguments:
//      domain     The index of the domain.  If there are NDomains, this
//                 value is guaranteed to be between 0 and NDomains-1,
//                 regardless of block origin.
//      varname    The name of the variable requested.
//
//  Programmer: childs -- generated by xml2avt
//  Creation:   Sun Feb 10 08:39:02 PDT 2008
//
// ****************************************************************************

vtkDataArray *
avtStreamGhostTestFileFormat::GetVar(int domain, const char *varname)
{
    double Xstart = ((domain % 2) == 1 ? 5. : 0.);
    vtkFloatArray *rv = vtkFloatArray::New();
    rv->SetNumberOfTuples(5*5*5);
    for (int k = 0 ; k < 5 ; k++)
        for (int j = 0 ; j < 5 ; j++)
            for (int i = 0 ; i < 5 ; i++)
                rv->SetTuple1(k*5*5 + j*5 + i, Xstart+i);

    return rv;
}


// ****************************************************************************
//  Method: avtStreamGhostTestFileFormat::GetVectorVar
//
//  Purpose:
//      Gets a vector variable associated with this file.  Although VTK has
//      support for many different types, the best bet is vtkFloatArray, since
//      that is supported everywhere through VisIt.
//
//  Arguments:
//      domain     The index of the domain.  If there are NDomains, this
//                 value is guaranteed to be between 0 and NDomains-1,
//                 regardless of block origin.
//      varname    The name of the variable requested.
//
//  Programmer: childs -- generated by xml2avt
//  Creation:   Sun Feb 10 08:39:02 PDT 2008
//
// ****************************************************************************

vtkDataArray *
avtStreamGhostTestFileFormat::GetVectorVar(int domain, const char *varname)
{
    EXCEPTION1(InvalidVariableException, varname);
}


